/**
  ******************************************************************************
  * @file    Queue.c 

  ******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "Queue.h"
#include "system_stm32f10x.h"
#include "stm32f10x.h"
#include "SystemConfig.h"
#include "stm32f10x_it.h"
#include "stdlib.h"
#include "string.h"
#include "task.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup SysTick
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

//fenris 20110128
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */

/**
 * @brief	QBuffer initail function
 * @param	q	QBuf structure pointer
 * @param	buf	circular buffer pointer
 * @param	len	circular buffer length
 * @return	none
 * @note	
 */
void QBuf_Init(QBuf *q, char *buf, unsigned short len)
{
	q->head	= 0;
	q->tail	= 0;
	q->buf	= buf;
	q->len	= len;
	q->use	= 0;
}

/**
 * @brief	Write data to QBuffer
 * @param	q	QBuf structure pointer
 * @param	buf	write data buffer
 * @param	len	write data length
 * @return	QBUF_FULL/QBUF_OK
 * @note	
 */
unsigned char QBuf_Write(QBuf *q, char *buf, unsigned short len)
{
	unsigned short i, j;
	
	/* check remain space */
	if (len > (q->len - q->use))
	{
		return QBUF_FULL;
	}
	
	/* write data */
	for (i = 0, j = q->head; i < len;)
	{
		q->buf[j++] = buf[i++];
		if (j == q->len)
		{
			j = 0;
		}
	}
	
	/* change head and use */
	ENTRY_CRITICAL_SECTION();
	q->head = j;
	q->use += len;
	EXIT_CRITICAL_SECTION();
	return QBUF_OK;
}

/**
 * @brief	Read data from QBuffer
 * @param	q	QBuf structure pointer
 * @param	buf	read data buffer
 * @param	len	read data length
 * @return	QBUF_EMPTY/QBUF_OK
 * @note	
 */
unsigned char QBuf_Read(QBuf *q, char *buf, unsigned short len)
{
	unsigned short i, j;
	
	if (len > q->use)
	{
		return QBUF_EMPTY;
	}
	
	/* read data */
	for (i = 0, j = q->tail; i < len;)
	{
		buf[i++] = q->buf[j++];
		if (j == q->len)
		{
			j = 0;
		}
	}
	
	/* change tail and use */
	ENTRY_CRITICAL_SECTION();
	q->tail = j;
	q->use -= len;
	EXIT_CRITICAL_SECTION();
	return QBUF_OK;
}

/**
 * @brief	Delete data from QBuffer
 * @param	q	QBuf structure pointer
 * @param	len	delete data length
 * @return	QBUF_EMPTY/QBUF_OK
 * @note	
 */
unsigned char QBuf_Del(QBuf *q, unsigned short len)
{
	if (len > q->use)
	{
		return QBUF_EMPTY;
	}
	
	/* change head and use */
	ENTRY_CRITICAL_SECTION();
	if (q->head < len)
		q->head = q->head + q->len - len;
	else
		q->head -= len;
	q->use -= len;
	EXIT_CRITICAL_SECTION();
	return QBUF_OK;
}

/**
 * @brief	Clear QBuffer
 * @param	q	QBuf structure pointer
 * @return	none
 * @note	
 */
void QBuf_Clear(QBuf *q)
{
	ENTRY_CRITICAL_SECTION();
	q->head	= 0;
	q->tail	= 0;
	q->use	= 0;
	EXIT_CRITICAL_SECTION();
}



/**
 * @brief	Check QBuffer is Full?
 * @param	q	QBuf structure pointer
 * @param	len	write data length for check
 * @return	QBUF_FULL/QBUF_OK
 * @note	
 */
unsigned char QBuf_ChkFull(QBuf *q,unsigned short len)
{
	//unsigned short i, j;
	
	/* check remain space */
	if (len > (q->len - q->use))
	{
		return QBUF_FULL;
	}
	return QBUF_OK;
}